package com.simple.util.time;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TimeZone;

/**
 * @program: simple_tools
 * @description:
 * @author: ChenWenLong
 * @create: 2019-06-04 16:19
 **/
public class DateUtil {

    //无时区的格式化
    public static final FastDateFormat ISO_DATETIME_FORMAT
            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
    //带时区的格式化
    public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT
            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
    //纯日期格式化
    public static final FastDateFormat ISO_DATE_FORMAT
            = FastDateFormat.getInstance("yyyy-MM-dd");
    //带时区的日期格式化
    public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT
            = FastDateFormat.getInstance("yyyy-MM-ddZZ");
    //不带时区的时间格式化
    public static final FastDateFormat ISO_TIME_FORMAT
            = FastDateFormat.getInstance("'T'HH:mm:ss");
    //带时区的时间格式化
    public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT
            = FastDateFormat.getInstance("'T'HH:mm:ssZZ");
    //没有T前缀的,非ISO8601规范的时间格式化
    public static final FastDateFormat ISO_TIME_NO_T_FORMAT
            = FastDateFormat.getInstance("HH:mm:ss");
    //带时区的,非ISO8601规范的时间格式化
    public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT
            = FastDateFormat.getInstance("HH:mm:ssZZ");
    public static final FastDateFormat SMTP_DATETIME_FORMAT
            = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
    //世界时间格式
    public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT");
    //每秒=1000毫秒
    public static final long MILLIS_PER_SECOND = 1000;
    //每分钟=60秒
    public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    //每小时=60分钟
    public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
    //每天=24小时
    public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
    //表示半个月,这个表示是上半旬还是下半旬
    public final static int SEMI_MONTH = 1001;

    public final static int RANGE_WEEK_SUNDAY = 1;
    public final static int RANGE_WEEK_MONDAY = 2;
    public final static int RANGE_WEEK_RELATIVE = 3;
    public final static int RANGE_WEEK_CENTER = 4;
    public final static int RANGE_MONTH_SUNDAY = 5;
    public final static int RANGE_MONTH_MONDAY = 6;

    private static final int[][] fields = {
            {Calendar.MILLISECOND},
            {Calendar.SECOND},
            {Calendar.MINUTE},
            {Calendar.HOUR_OF_DAY, Calendar.HOUR},
            {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM},
            {Calendar.MONTH, SEMI_MONTH},
            {Calendar.YEAR},
            {Calendar.ERA}};

    /**
     * 功能描述:
     * 〈判断是否是同一天,接受Date类型〉
     *
     * @params : [date1, date2]
     * @return : boolean
     * @author : cwl
     * @date : 2019/6/6 11:00
     */
    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return isSameDay(cal1, cal2);
    }

    /**
     * 功能描述:
     * 〈判断是否是同一天,接受Calendar〉
     *
     * @params : [cal1, cal2]
     * @return : boolean
     * @author : cwl
     * @date : 2019/6/6 11:01
     */
    public static boolean isSameDay(Calendar cal1, Calendar cal2) {
        if (cal1 == null || cal2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
                cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
    }

    /**
     * 功能描述:
     * 〈判断是否是同一时间,接受Date类型〉
     *
     * @params : [date1, date2]
     * @return : boolean
     * @author : cwl
     * @date : 2019/6/6 11:02
     */
    public static boolean isSameTime(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        return date1.getTime() == date2.getTime();
    }

    /**
     * 功能描述:
     * 〈判断是否是同一时间,接受Calendar〉
     *
     * @params : [cal1, cal2]
     * @return : boolean
     * @author : cwl
     * @date : 2019/6/6 11:03
     */
    public static boolean isSameTime(Calendar cal1, Calendar cal2) {
        if (cal1 == null || cal2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        return cal1.getTime().getTime() == cal2.getTime().getTime();
    }

    /**
     * 功能描述:
     * 〈是否是同一地区是时间,即将二手Calendar类型.Date类型并没有地区这种说法〉
     *
     * @params : [cal1, cal2]
     * @return : boolean
     * @author : cwl
     * @date : 2019/6/6 11:07
     */
    public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) {
        if (cal1 == null || cal2 == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) &&
                cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) &&
                cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) &&
                cal1.get(Calendar.HOUR) == cal2.get(Calendar.HOUR) &&
                cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
                cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
                cal1.getClass() == cal2.getClass());
    }

    /**
     * 功能描述:
     * 〈尝试用不同的格式去格式化字符串日期〉
     *
     * @params : [str, parsePatterns]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:19
     */
    public static Date parseDate(String str, String[] parsePatterns) throws ParseException {
        if (str == null || parsePatterns == null) {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }

        SimpleDateFormat parser = null;
        ParsePosition pos = new ParsePosition(0);
        for (int i = 0; i < parsePatterns.length; i++) {
            if (i == 0) {
                parser = new SimpleDateFormat(parsePatterns[0]);
            } else {
                parser.applyPattern(parsePatterns[i]);
            }
            pos.setIndex(0);
            Date date = parser.parse(str, pos);
            if (date != null && pos.getIndex() == str.length()) {
                return date;
            }
        }
        throw new ParseException("Unable to parse the date: " + str, -1);
    }

    /**
     *
     * @param str
     * @param parsePatterns
     * @return
     * @throws ParseException
     */
    public static Date parseDate(String str, String parsePatterns) throws ParseException {
        if (str == null || parsePatterns == null) {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }

        SimpleDateFormat parser = new SimpleDateFormat(parsePatterns);
        ParsePosition pos = new ParsePosition(0);
        pos.setIndex(0);
        Date date = parser.parse(str, pos);
        if (date != null && pos.getIndex() == str.length()) {
            return date;
        }
        throw new ParseException("Unable to parse the date: " + str, -1);
    }

    /**
     * 功能描述:
     * 〈解析时间格式〉
     *
     * @params : [str]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/10/17 16:47
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 功能描述:
     * 〈加amount年〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:22
     */
    public static Date addYears(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    /**
     * 功能描述:
     * 〈加amount月〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:22
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    /**
     * 功能描述:
     * 〈加amount月〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:23
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, Calendar.WEEK_OF_YEAR, amount);
    }

    /**
     * 功能描述:
     * 〈加amount天〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:23
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    /**
     * 功能描述:
     * 〈标准格式化时间.传入毫秒数mills和pattern格式〉
     *
     * @params : [millis, pattern]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:29
     */
    public static String formatUTC(long millis, String pattern) {
        return format(new Date(millis), pattern, UTC_TIME_ZONE, null);
    }

    /**
     * 功能描述:
     * 〈加amount小时〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:24
     */
    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }


    /**
     * 功能描述:
     * 〈标准格式化时间,传入date时间格式,pattern格式〉
     *
     * @params : [date, pattern]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:30
     */
    public static String formatUTC(Date date, String pattern) {
        return format(date, pattern, UTC_TIME_ZONE, null);
    }

    /**
     * 功能描述:
     * 〈加amount分钟〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:24
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    /**
     * 功能描述:
     * 〈加amount秒〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:24
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    /**
     * 功能描述:
     * 〈加amount毫秒〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:33
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    /**
     * 功能描述:
     * 〈添加年/月/日/时/分/秒/毫秒 amount为添加量〉
     *
     * @params : [date, calendarField, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:34
     */
    public static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 功能描述:
     * 〈设置date年份,并返回一个新的日期〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:35
     */
    public static Date setYears(Date date, int amount) {
        return set(date, Calendar.YEAR, amount);
    }

    /**
     * 功能描述:
     * 〈设置date月份,返回一个新的日期〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:36
     */
    public static Date setMonths(Date date, int amount) {
        return set(date, Calendar.MONTH, amount);
    }

    /**
     * 功能描述:
     * 〈设置date日期,返回一个新的日期〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:37
     */
    public static Date setDays(Date date, int amount) {
        return set(date, Calendar.DAY_OF_MONTH, amount);
    }

    /**
     * 功能描述:
     * 〈设置时间,返回一个新的时间〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:38
     */
    public static Date setHours(Date date, int amount) {
        return set(date, Calendar.HOUR_OF_DAY, amount);
    }

    /**
     * 功能描述:
     * 〈设置时间,返回一个新的时间〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:38
     */
    public static Date setMinutes(Date date, int amount) {
        return set(date, Calendar.MINUTE, amount);
    }

    /**
     * 功能描述:
     * 〈设置时间,返回一个新的时间〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:39
     */
    public static Date setSeconds(Date date, int amount) {
        return set(date, Calendar.SECOND, amount);
    }

    /**
     * 功能描述:
     * 〈设置时间,返回一个新的时间〉
     *
     * @params : [date, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:39
     */
    public static Date setMilliseconds(Date date, int amount) {
        return set(date, Calendar.MILLISECOND, amount);
    }

    /**
     * 功能描述:
     * 〈设置时间〉
     *
     * @params : [date, calendarField, amount]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 11:40
     */
    private static Date set(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        // getInstance() returns a new object, so this method is thread safe.
        Calendar c = Calendar.getInstance();
        c.setLenient(false);
        c.setTime(date);
        c.set(calendarField, amount);
        return c.getTime();
    }

    /**
     * 功能描述:
     * 〈对日期Date类型进行四舍五入〉
     *
     * @params : [date, field]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 13:58
     */
    public static Date round(Date date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar gval = Calendar.getInstance();
        gval.setTime(date);
        modify(gval, field, true);
        return gval.getTime();
    }

    /**
     * 功能描述:
     * 〈对日历类Calander类型进行四舍五入〉
     *
     * @params : [date, field]
     * @return : java.util.Calendar
     * @author : cwl
     * @date : 2019/6/6 13:58
     */
    public static Calendar round(Calendar date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar rounded = (Calendar) date.clone();
        modify(rounded, field, true);
        return rounded;
    }

    /**
     * 功能描述:
     * 〈对Date类型或者Calendar类型进行四舍五入〉
     *
     * @params : [date, field]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 14:02
     */
    public static Date round(Object date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        if (date instanceof Date) {
            return round((Date) date, field);
        } else if (date instanceof Calendar) {
            return round((Calendar) date, field).getTime();
        } else {
            throw new ClassCastException("Could not round " + date);
        }
    }

    /**
     * 功能描述:
     * 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.仅接受日期类Date〉
     *
     * @params : [date, field]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 14:04
     */
    public static Date truncate(Date date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar gval = Calendar.getInstance();
        gval.setTime(date);
        modify(gval, field, false);
        return gval.getTime();
    }

    /**
     * 功能描述:
     * 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.仅接受日历类Calendar〉
     *
     * @params : [date, field]
     * @return : java.util.Calendar
     * @author : cwl
     * @date : 2019/6/6 14:06
     */
    public static Calendar truncate(Calendar date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar truncated = (Calendar) date.clone();
        modify(truncated, field, false);
        return truncated;
    }

    /**
     * 功能描述:
     * 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.接受日历类和日期类〉
     *
     * @params : [date, field]
     * @return : java.util.Date
     * @author : cwl
     * @date : 2019/6/6 14:09
     */
    public static Date truncate(Object date, int field) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        if (date instanceof Date) {
            return truncate((Date) date, field);
        } else if (date instanceof Calendar) {
            return truncate((Calendar) date, field).getTime();
        } else {
            throw new ClassCastException("Could not truncate " + date);
        }
    }

    private static void modify(Calendar val, int field, boolean round) {
        if (val.get(Calendar.YEAR) > 280000000) {
            throw new ArithmeticException("Calendar value too large for accurate calculations");
        }

        if (field == Calendar.MILLISECOND) {
            return;
        }
        // 手动截断毫秒、秒和分钟，而不是使用日历方法。
        Date date = val.getTime();
        long time = date.getTime();
        boolean done = false;

        // 截断毫秒
        int millisecs = val.get(Calendar.MILLISECOND);
        if (!round || millisecs < 500) {
            time = time - millisecs;
        }
        if (field == Calendar.SECOND) {
            done = true;
        }

        // 截断秒
        int seconds = val.get(Calendar.SECOND);
        if (!done && (!round || seconds < 30)) {
            time = time - (seconds * 1000L);
        }
        if (field == Calendar.MINUTE) {
            done = true;
        }

        // 截断分钟
        int minutes = val.get(Calendar.MINUTE);
        if (!done && (!round || minutes < 30)) {
            time = time - (minutes * 60000L);
        }

        // 重新设置时间
        if (date.getTime() != time) {
            date.setTime(time);
            val.setTime(date);
        }
        // ----------------- Fix for LANG-59 ----------------------- END ----------------
        boolean roundUp = false;
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[i].length; j++) {
                if (fields[i][j] == field) {
                    //This is our field... we stop looping
                    if (round && roundUp) {
                        if (field == SEMI_MONTH) {
                            //判断这是每个月的上半旬还是下半旬,如果是上半旬,那么就加上15天减去1个月
                            if (val.get(Calendar.DATE) == 1) {
                                val.add(Calendar.DATE, 15);
                            } else {
                                val.add(Calendar.DATE, -15);
                                val.add(Calendar.MONTH, 1);
                            }
                        } else {
                            //这里需要+1,因为最后一个数字是四舍五入的
                            val.add(fields[i][0], 1);
                        }
                    }
                    return;
                }
            }
            // 对各种不同的类型进行四舍五入
            int offset = 0;
            boolean offsetSet = false;
            switch (field) {
                case SEMI_MONTH:
                    if (fields[i][0] == Calendar.DATE) {
                        offset = val.get(Calendar.DATE) - 1;
                        //如果offset大于15,那么说明是在下半个月
                        if (offset >= 15) {
                            offset -= 15;
                        }
                        //记录下我们是在这个范围的上半部分还是下半部分
                        roundUp = offset > 7;
                        offsetSet = true;
                    }
                    break;
                case Calendar.AM_PM:
                    if (fields[i][0] == Calendar.HOUR_OF_DAY) {
                        //对小时字段的值进行处理
                        offset = val.get(Calendar.HOUR_OF_DAY);
                        if (offset >= 12) {
                            offset -= 12;
                        }
                        roundUp = offset > 6;
                        offsetSet = true;
                    }
                    break;
            }
            if (!offsetSet) {
                int min = val.getActualMinimum(fields[i][0]);
                int max = val.getActualMaximum(fields[i][0]);
                //从允许的最小值计算偏移量
                offset = val.get(fields[i][0]) - min;
                //如果这是介于最小值和最大值之间的一半以上，则设置汇总
                roundUp = offset > ((max - min) / 2);
            }
            //我们需要移除这个字段
            if (offset != 0) {
                val.set(fields[i][0], val.get(fields[i][0]) - offset);
            }
        }
        throw new IllegalArgumentException("The field " + field + " is not supported");

    }

    /**
     * 功能描述:
     * 〈通过毫秒数millis,指定地区Locale,指定格式pattern 标准格式化时间〉
     *
     * @params : [millis, pattern, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:31
     */
    public static String formatUTC(long millis, String pattern, Locale locale) {
        return format(new Date(millis), pattern, UTC_TIME_ZONE, locale);
    }

    /**
     * 功能描述:
     * 〈返回一个从focus开始的迭代器〉
     *
     * @params : [focus, rangeStyle]
     * @return : java.util.Iterator
     * @author : cwl
     * @date : 2019/6/6 14:38
     */
    public static Iterator iterator(Date focus, int rangeStyle) {
        if (focus == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar gval = Calendar.getInstance();
        gval.setTime(focus);
        return iterator(gval, rangeStyle);
    }

    /**
     * 功能描述:
     * 〈返回一个从focus开始的迭代器〉
     *
     * @params : [focus, rangeStyle]
     * @return : java.util.Iterator
     * @author : cwl
     * @date : 2019/6/6 14:54
     */
    public static Iterator iterator(Calendar focus, int rangeStyle) {
        if (focus == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar start = null;
        Calendar end = null;
        int startCutoff = Calendar.SUNDAY;
        int endCutoff = Calendar.SATURDAY;
        switch (rangeStyle) {
            case RANGE_MONTH_SUNDAY:
            case RANGE_MONTH_MONDAY:
                // 从fucus当中截取它的月份作为起始月
                start = truncate(focus, Calendar.MONTH);
                // 拷贝起始月作为结束月,并且对结束月进行加一个月减一天的操作
                end = (Calendar) start.clone();
                end.add(Calendar.MONTH, 1);
                end.add(Calendar.DATE, -1);
                // 循环开始到开始到开始时间的前一个周一或者是周日
                if (rangeStyle == RANGE_MONTH_MONDAY) {
                    startCutoff = Calendar.MONDAY;
                    endCutoff = Calendar.SUNDAY;
                }
                break;
            case RANGE_WEEK_SUNDAY:
            case RANGE_WEEK_MONDAY:
            case RANGE_WEEK_RELATIVE:
            case RANGE_WEEK_CENTER:
                // 从fucus当中截取它的月份作为起始月
                start = truncate(focus, Calendar.DATE);
                end = truncate(focus, Calendar.DATE);
                switch (rangeStyle) {
                    case RANGE_WEEK_SUNDAY:
                        // already set by default
                        break;
                    case RANGE_WEEK_MONDAY:
                        startCutoff = Calendar.MONDAY;
                        endCutoff = Calendar.SUNDAY;
                        break;
                    case RANGE_WEEK_RELATIVE:
                        startCutoff = focus.get(Calendar.DAY_OF_WEEK);
                        endCutoff = startCutoff - 1;
                        break;
                    case RANGE_WEEK_CENTER:
                        startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3;
                        endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3;
                        break;
                }
                break;
            default:
                throw new IllegalArgumentException("The range style " + rangeStyle + " is not valid.");
        }
        if (startCutoff < Calendar.SUNDAY) {
            startCutoff += 7;
        }
        if (startCutoff > Calendar.SATURDAY) {
            startCutoff -= 7;
        }
        if (endCutoff < Calendar.SUNDAY) {
            endCutoff += 7;
        }
        if (endCutoff > Calendar.SATURDAY) {
            endCutoff -= 7;
        }
        while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) {
            start.add(Calendar.DATE, -1);
        }
        while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) {
            end.add(Calendar.DATE, 1);
        }
        return new DateIterator(start, end);
    }

    /**
     * 功能描述:
     * 〈获取一个日期类date或者是日历类Calendar迭代器对象〉
     *
     * @params : [focus, rangeStyle]
     * @return : java.util.Iterator
     * @author : cwl
     * @date : 2019/6/6 14:59
     */
    public static Iterator iterator(Object focus, int rangeStyle) {
        if (focus == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        if (focus instanceof Date) {
            return iterator((Date) focus, rangeStyle);
        } else if (focus instanceof Calendar) {
            return iterator((Calendar) focus, rangeStyle);
        } else {
            throw new ClassCastException("Could not iterate based on " + focus);
        }
    }

    //============================分割时间-仅Date类型==============================
    /**
     * 功能描述:
     * 〈分割出对应时间点的毫秒数〉
     *
     * @params : [date, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:03
     */
    public static long getFragmentInMilliseconds(Date date, int fragment) {
        return getFragment(date, fragment, Calendar.MILLISECOND);
    }

    /**
     * 功能描述:
     * 〈分割出对应时间的秒数〉
     *
     * @params : [date, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:03
     */
    public static long getFragmentInSeconds(Date date, int fragment) {
        return getFragment(date, fragment, Calendar.SECOND);
    }

    /**
     * 功能描述:
     * 〈分割出对应时间的秒数〉
     *
     * @params : [date, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:08
     */
    public static long getFragmentInMinutes(Date date, int fragment) {
        return getFragment(date, fragment, Calendar.MINUTE);
    }

    /**
     * 功能描述:
     * 〈分割出对应时间段的小时数〉
     *
     * @params : [date, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:08
     */
    public static long getFragmentInHours(Date date, int fragment) {
        return getFragment(date, fragment, Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述:
     * 〈分割出对应时间的天数〉
     *
     * @params : [date, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:10
     */
    public static long getFragmentInDays(Date date, int fragment) {
        return getFragment(date, fragment, Calendar.DAY_OF_YEAR);
    }
    //============================分割时间-仅Date类型==============================

    //==========================分割时间-仅Calendar类型============================
    /**
     * 功能描述:
     * 〈分割时间毫秒数〉
     *
     * @params : [calendar, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:12
     */
    public static long getFragmentInMilliseconds(Calendar calendar, int fragment) {
        return getFragment(calendar, fragment, Calendar.MILLISECOND);
    }

    /**
     * 功能描述:
     * 〈分割时间秒数〉
     *
     * @params : [calendar, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:13
     */
    public static long getFragmentInSeconds(Calendar calendar, int fragment) {
        return getFragment(calendar, fragment, Calendar.SECOND);
    }

    /**
     * 功能描述:
     * 〈分割时间分钟数〉
     *
     * @params : [calendar, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:13
     */
    public static long getFragmentInMinutes(Calendar calendar, int fragment) {
        return getFragment(calendar, fragment, Calendar.MINUTE);
    }

    /**
     * 功能描述:
     * 〈分割时间小时数〉
     *
     * @params : [calendar, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:14
     */
    public static long getFragmentInHours(Calendar calendar, int fragment) {
        return getFragment(calendar, fragment, Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述:
     * 〈分割时间天数〉
     *
     * @params : [calendar, fragment]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:14
     */
    public static long getFragmentInDays(Calendar calendar, int fragment) {
        return getFragment(calendar, fragment, Calendar.DAY_OF_YEAR);
    }

    /**
     * 功能描述:
     * 〈任意单元碎片的进行切割日期〉
     *
     * @params : [date, fragment, unit]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:16
     */
    private static long getFragment(Date date, int fragment, int unit) {
        if(date == null) {
            throw  new IllegalArgumentException("The date must not be null");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getFragment(calendar, fragment, unit);
    }

    /**
     * 功能描述:
     * 〈任意单元碎片的进行切割日历类时间〉
     *
     * @params : [calendar, fragment, unit]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:17
     */
    private static long getFragment(Calendar calendar, int fragment, int unit) {
        if(calendar == null) {
            throw  new IllegalArgumentException("The date must not be null");
        }
        long millisPerUnit = getMillisPerUnit(unit);
        long result = 0;

        // 大于一天的情况都分解成天来计算
        switch (fragment) {
            case Calendar.YEAR:
                result += (calendar.get(Calendar.DAY_OF_YEAR) * MILLIS_PER_DAY) / millisPerUnit;
                break;
            case Calendar.MONTH:
                result += (calendar.get(Calendar.DAY_OF_MONTH) * MILLIS_PER_DAY) / millisPerUnit;
                break;
        }

        switch (fragment) {
            // Number of days already calculated for these cases
            case Calendar.YEAR:
            case Calendar.MONTH:

                // The rest of the valid cases
            case Calendar.DAY_OF_YEAR:
            case Calendar.DATE:
                result += (calendar.get(Calendar.HOUR_OF_DAY) * MILLIS_PER_HOUR) / millisPerUnit;
            case Calendar.HOUR_OF_DAY:
                result += (calendar.get(Calendar.MINUTE) * MILLIS_PER_MINUTE) / millisPerUnit;
            case Calendar.MINUTE:
                result += (calendar.get(Calendar.SECOND) * MILLIS_PER_SECOND) / millisPerUnit;
            case Calendar.SECOND:
                result += (calendar.get(Calendar.MILLISECOND) * 1) / millisPerUnit;
                break;
            case Calendar.MILLISECOND: break;//never useful
            default: throw new IllegalArgumentException("The fragment " + fragment + " is not supported");
        }
        return result;
    }

    /**
     * 功能描述:
     * 〈返回任意单元对应的毫秒数〉
     *
     * @params : [unit]
     * @return : long
     * @author : cwl
     * @date : 2019/6/6 15:19
     */
    private static long getMillisPerUnit(int unit) {
        long result;
        switch (unit) {
            case Calendar.DAY_OF_YEAR:
            case Calendar.DATE:
                result = MILLIS_PER_DAY;
                break;
            case Calendar.HOUR_OF_DAY:
                result = MILLIS_PER_HOUR;
                break;
            case Calendar.MINUTE:
                result = MILLIS_PER_MINUTE;
                break;
            case Calendar.SECOND:
                result = MILLIS_PER_SECOND;
                break;
            case Calendar.MILLISECOND:
                result = 1;
                break;
            default: throw new IllegalArgumentException("The unit " + unit + " cannot be represented is milleseconds");
        }
        return result;
    }

    /**
     * 功能描述:
     * 〈指定日期date格式化〉
     *
     * @params : [date, pattern, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:32
     */
    public static String formatUTC(Date date, String pattern, Locale locale) {
        return format(date, pattern, UTC_TIME_ZONE, locale);
    }

    /**
     * 功能描述:
     * 〈指定格式pattern进行毫秒数格式化〉
     *
     * @params : [millis, pattern]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:32
     */
    public static String format(long millis, String pattern) {
        return format(new Date(millis), pattern, null, null);
    }

    /**
     * 功能描述:
     * 〈指定pattern格式化date日期〉
     *
     * @params : [date, pattern]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:33
     */
    public static String format(Date date, String pattern) {
        return format(date, pattern, null, null);
    }

    /**
     * 功能描述:
     * 〈指定格式化Calendar日历类〉
     *
     * @params : [calendar, pattern]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:33
     */
    public static String format(Calendar calendar, String pattern) {
        return format(calendar, pattern, null, null);
    }

    /**
     * 功能描述:
     * 〈指定时区和格式pattern格式化millis〉
     *
     * @params : [millis, pattern, timeZone]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:34
     */
    public static String format(long millis, String pattern, TimeZone timeZone) {
        return format(new Date(millis), pattern, timeZone, null);
    }

    /**
     * 功能描述:
     * 〈指定日期date和timeZone时区以及格式pattern进行格式化〉
     *
     * @params : [date, pattern, timeZone]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:35
     */
    public static String format(Date date, String pattern, TimeZone timeZone) {
        return format(date, pattern, timeZone, null);
    }

    /**
     * 功能描述:
     * 〈指定时区timeZone,格式pattern,日历类calendar格式化时间〉
     *
     * @params : [calendar, pattern, timeZone]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:35
     */
    public static String format(Calendar calendar, String pattern, TimeZone timeZone) {
        return format(calendar, pattern, timeZone, null);
    }

    /**
     * 功能描述:
     * 〈指定格式和地区格式化date〉
     *
     * @params : [date, pattern, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 18:00
     */
    public static String format(Date date, String pattern, Locale locale) {
        return format(date, pattern, null, locale);
    }

    /**
     * 功能描述:
     * 〈指定地区和格式,格式化毫秒数〉
     *
     * @params : [millis, pattern, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 17:37
     */
    public static String format(long millis, String pattern, Locale locale) {
        return format(new Date(millis), pattern, null, locale);
    }

    /**
     * 功能描述:
     * 〈指定格式和地区格式化日历类〉
     *
     * @params : [calendar, pattern, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 18:01
     */
    public static String format(Calendar calendar, String pattern, Locale locale) {
        return format(calendar, pattern, null, locale);
    }

    /**
     * 功能描述:
     * 〈指定格式时区和地区格式化毫秒数〉
     *
     * @params : [millis, pattern, timeZone, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 18:02
     */
    public static String format(long millis, String pattern, TimeZone timeZone, Locale locale) {
        return format(new Date(millis), pattern, timeZone, locale);
    }

    /**
     * 功能描述:
     * 〈指定格式/时区/地区格式化日期〉
     *
     * @params : [date, pattern, timeZone, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 18:04
     */
    public static String format(Date date, String pattern, TimeZone timeZone, Locale locale) {
        FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
        return df.format(date);
    }

    /**
     * 功能描述:
     * 〈指定格式/时区/地区格式化日历类〉
     *
     * @params : [calendar, pattern, timeZone, locale]
     * @return : java.lang.String
     * @author : cwl
     * @date : 2019/6/5 18:05
     */
    public static String format(Calendar calendar, String pattern, TimeZone timeZone, Locale locale) {
        FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
        return df.format(calendar);
    }

    //迭代日期的构造器
    static class DateIterator implements Iterator {
        private final Calendar endFinal;
        private final Calendar spot;

        /**
         * 功能描述:
         * 〈从开始日期startFinal到结束日期endFinal的迭代器〉
         *
         * @params : [startFinal, endFinal]
         * @return :
         * @author : cwl
         * @date : 2019/6/6 14:43
         */
        DateIterator(Calendar startFinal, Calendar endFinal) {
            super();
            this.endFinal = endFinal;
            spot = startFinal;
            spot.add(Calendar.DATE, -1);
        }

        /**
         * 功能描述:
         * 〈迭代器是否已经达到了结束日期〉
         *
         * @params : []
         * @return : boolean
         * @author : cwl
         * @date : 2019/6/6 14:44
         */
        public boolean hasNext() {
            return spot.before(endFinal);
        }

        /**
         * 功能描述:
         * 〈在迭代器循环当中,返回下一个日历对象〉
         *
         * @params : []
         * @return : java.lang.Object
         * @author : cwl
         * @date : 2019/6/6 14:45
         */
        public Object next() {
            if (spot.equals(endFinal)) {
                throw new NoSuchElementException();
            }
            spot.add(Calendar.DATE, 1);
            return spot.clone();
        }

        /**
         * 功能描述:
         * 〈覆盖于父类的方法,用于抛出一个不可操作的异常〉
         *
         * @params : []
         * @return : void
         * @author : cwl
         * @date : 2019/6/6 14:46
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    //快速日期格式化
    public static class FastDateFormat extends Format{
        //支持序列化
        private static final long serialVersionUID = 1L;
        //全样式模式的常量,表示日期格式为全样式
        public static final int FULL = DateFormat.FULL;
        //长区域的时间样式
        public static final int LONG = DateFormat.LONG;
        //中间地区地区的时间样式
        public static final int MEDIUM = DateFormat.MEDIUM;
        //短区域的时间样式
        public static final int SHORT = DateFormat.SHORT;
        //默认的时间样式
        private static String cDefaultPattern;
        //对象缓存
        private static final Map cInstanceCache = new HashMap(7);
        private static final Map cDateInstanceCache = new HashMap(7);
        private static final Map cTimeInstanceCache = new HashMap(7);
        private static final Map cDateTimeInstanceCache = new HashMap(7);
        private static final Map cTimeZoneDisplayCache = new HashMap(7);

        private final String mPattern;//日期样式
        private final TimeZone mTimeZone;//时区
        private final boolean mTimeZoneForced;//是否使用默认时区
        private final Locale mLocale;//地区
        private final boolean mLocaleForced;//是否使用默认地区
        private transient int mMaxLengthEstimate;//预计的最大长度

        private transient Rule[] mRules;

        /**
         * 功能描述:
         * 〈获取一个默认的日期格式化对象〉
         *
         * @params : []
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:21
         */
        public static FastDateFormat getInstance() {
            return getInstance(getDefaultPattern(), null, null);
        }

        /**
         * 功能描述:
         * 〈获取一个指定的日期格式化对象,指定格式为pattern〉
         *
         * @params : [pattern]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:22
         */
        public static FastDateFormat getInstance(String pattern) {
            return getInstance(pattern, null, null);
        }

        /**
         * 功能描述:
         * 〈创建一个指定格式pattern与时区timeZone的日期格式化对象〉
         *
         * @params : [pattern, timeZone]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:23
         */
        public static FastDateFormat getInstance(String pattern, TimeZone timeZone) {
            return getInstance(pattern, timeZone, null);
        }

        /**
         * 功能描述:
         * 〈创建一个指定格式pattern和指定地区locale的日期格式化对象〉
         *
         * @params : [pattern, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:24
         */
        public static FastDateFormat getInstance(String pattern, Locale locale) {
            return getInstance(pattern, null, locale);
        }

        /**
         * 功能描述:
         * 〈创建一个指定格式pattern,指定时区timeZone,指定地区locale的日期格式化对象,为了避免重复创建,使用synchronize同步方法〉
         *
         * @params : [pattern, timeZone, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:25
         */
        public static synchronized FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) {
            FastDateFormat emptyFormat = new FastDateFormat(pattern, timeZone, locale);
            FastDateFormat format = (FastDateFormat) cInstanceCache.get(emptyFormat);
            if (format == null) {
                format = emptyFormat;
                format.init();  // convert shell format into usable one
                cInstanceCache.put(format, format);  // this is OK!
            }
            return format;
        }

        /**
         * 功能描述:
         * 〈获得指定日期样式的日期格式化对象〉
         *
         * @params : [style]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:26
         */
        public static FastDateFormat getDateInstance(int style) {
            return getDateInstance(style, null, null);
        }

        /**
         * 功能描述:
         * 〈获得指定日期样式style和地区locale的日期格式化对象〉
         *
         * @params : [style, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:27
         */
        public static FastDateFormat getDateInstance(int style, Locale locale) {
            return getDateInstance(style, null, locale);
        }

        /**
         * 功能描述:
         * 〈获得指定日期样式style和时区timeZone的日期格式化对象〉
         *
         * @params : [style, timeZone]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:28
         */
        public static FastDateFormat getDateInstance(int style, TimeZone timeZone) {
            return getDateInstance(style, timeZone, null);
        }

        /**
         * 功能描述:
         * 〈获得指定日期样式style和时区timeZone以及指定地区locale的日期格式化对象〉
         *
         * @params : [style, timeZone, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:29
         */
        public static synchronized FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale) {
            Object key = new Integer(style);
            if (timeZone != null) {
                key = new Pair(key, timeZone);
            }

            if (locale == null) {
                locale = Locale.getDefault();
            }

            key = new Pair(key, locale);

            FastDateFormat format = (FastDateFormat) cDateInstanceCache.get(key);
            if (format == null) {
                try {
                    SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateInstance(style, locale);
                    String pattern = formatter.toPattern();
                    format = getInstance(pattern, timeZone, locale);
                    cDateInstanceCache.put(key, format);

                } catch (ClassCastException ex) {
                    throw new IllegalArgumentException("No date pattern for locale: " + locale);
                }
            }
            return format;
        }

        /**
         * 功能描述:
         * 〈获得指定时间样式style的日期格式化对象〉
         *
         * @params : [style]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:30
         */
        public static FastDateFormat getTimeInstance(int style) {
            return getTimeInstance(style, null, null);
        }

        /**
         * 功能描述:
         * 〈获得指定地区locale和样式style的时间格式化对象〉
         *
         * @params : [style, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:31
         */
        public static FastDateFormat getTimeInstance(int style, Locale locale) {
            return getTimeInstance(style, null, locale);
        }

        /**
         * 功能描述:
         * 〈获得指定样式style和指定时区timeZone的时间格式化对象〉
         *
         * @params : [style, timeZone]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:31
         */
        public static FastDateFormat getTimeInstance(int style, TimeZone timeZone) {
            return getTimeInstance(style, timeZone, null);
        }

        /**
         * 功能描述:
         * 〈获得指定样式style和指定时区timeZone以及指定地区locale的时间格式化对象〉
         *
         * @params : [style, timeZone, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:32
         */
        public static synchronized FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale) {
            Object key = new Integer(style);
            if (timeZone != null) {
                key = new Pair(key, timeZone);
            }
            if (locale != null) {
                key = new Pair(key, locale);
            }

            FastDateFormat format = (FastDateFormat) cTimeInstanceCache.get(key);
            if (format == null) {
                if (locale == null) {
                    locale = Locale.getDefault();
                }

                try {
                    SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getTimeInstance(style, locale);
                    String pattern = formatter.toPattern();
                    format = getInstance(pattern, timeZone, locale);
                    cTimeInstanceCache.put(key, format);

                } catch (ClassCastException ex) {
                    throw new IllegalArgumentException("No date pattern for locale: " + locale);
                }
            }
            return format;
        }

        /**
         * 功能描述:
         * 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle〉
         *
         * @params : [dateStyle, timeStyle]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:33
         */
        public static FastDateFormat getDateTimeInstance(
                int dateStyle, int timeStyle) {
            return getDateTimeInstance(dateStyle, timeStyle, null, null);
        }

        /**
         * 功能描述:
         * 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定地区locale〉
         *
         * @params : [dateStyle, timeStyle, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:34
         */
        public static FastDateFormat getDateTimeInstance(
                int dateStyle, int timeStyle, Locale locale) {
            return getDateTimeInstance(dateStyle, timeStyle, null, locale);
        }

        /**
         * 功能描述:
         * 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定时区timeZone〉
         *
         * @params : [dateStyle, timeStyle, timeZone]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:34
         */
        public static FastDateFormat getDateTimeInstance(
                int dateStyle, int timeStyle, TimeZone timeZone) {
            return getDateTimeInstance(dateStyle, timeStyle, timeZone, null);
        }

        /**
         * 功能描述:
         * 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定时区timeZone,指定地区locale〉
         *
         * @params : [dateStyle, timeStyle, timeZone, locale]
         * @return : com.simple.util.time.DateUtil.FastDateFormat
         * @author : cwl
         * @date : 2019/6/4 17:35
         */
        public static synchronized FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone,
                                                                      Locale locale) {

            Object key = new Pair(new Integer(dateStyle), new Integer(timeStyle));
            if (timeZone != null) {
                key = new Pair(key, timeZone);
            }
            if (locale == null) {
                locale = Locale.getDefault();
            }
            key = new Pair(key, locale);

            FastDateFormat format = (FastDateFormat) cDateTimeInstanceCache.get(key);
            if (format == null) {
                try {
                    SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyle, timeStyle,
                            locale);
                    String pattern = formatter.toPattern();
                    format = getInstance(pattern, timeZone, locale);
                    cDateTimeInstanceCache.put(key, format);

                } catch (ClassCastException ex) {
                    throw new IllegalArgumentException("No date time pattern for locale: " + locale);
                }
            }
            return format;
        }

        /**
         * 功能描述:
         * 〈获取时区显示名称，使用缓存以提高性能.daylight为是否是白天,style选择样式,locale选择地区〉
         *
         * @params : [tz, daylight, style, locale]
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:37
         */
        public static synchronized String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale) {
            Object key = new TimeZoneDisplayKey(tz, daylight, style, locale);
            String value = (String) cTimeZoneDisplayCache.get(key);
            if (value == null) {
                // This is a very slow call, so cache the results.
                value = tz.getDisplayName(daylight, style, locale);
                cTimeZoneDisplayCache.put(key, value);
            }
            return value;
        }

        /**
         * 功能描述:
         * 〈获得默认的日期格式〉
         *
         * @params : []
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:38
         */
        private static synchronized String getDefaultPattern() {
            if (cDefaultPattern == null) {
                cDefaultPattern = new SimpleDateFormat().toPattern();
            }
            return cDefaultPattern;
        }
        
        /**
         * 功能描述: 
         * 〈创建一个指定样式pattern,指定时区timeZone,指定地区locale的日期格式化对象〉
         *
         * @params : [pattern, timeZone, locale]
         * @return :
         * @author : cwl
         * @date : 2019/6/4 17:39
         */
        private FastDateFormat(String pattern, TimeZone timeZone, Locale locale) {
            super();
            if (pattern == null) {
                throw new IllegalArgumentException("The pattern must not be null");
            }
            mPattern = pattern;

            mTimeZoneForced = (timeZone != null);
            if (timeZone == null) {
                timeZone = TimeZone.getDefault();
            }
            mTimeZone = timeZone;

            mLocaleForced = (locale != null);
            if (locale == null) {
                locale = Locale.getDefault();
            }
            mLocale = locale;
        }

        /**
         * 功能描述:
         * 〈初始化日期格式〉
         *
         * @params : []
         * @return : void
         * @author : cwl
         * @date : 2019/6/4 17:44
         */
        private void init() {
            List rulesList = parsePattern();
            mRules = (Rule[]) rulesList.toArray(new Rule[rulesList.size()]);

            int len = 0;
            for (int i=mRules.length; --i >= 0; ) {
                len += mRules[i].estimateLength();
            }

            mMaxLengthEstimate = len;
        }

        /**
         * 功能描述:
         * 〈获得给定模式的规则集合〉
         *
         * @params : []
         * @return : java.util.List
         * @author : cwl
         * @date : 2019/6/4 17:45
         */
        private List parsePattern() {
            DateFormatSymbols symbols = new DateFormatSymbols(mLocale);
            List rules = new ArrayList();

            String[] ERAs = symbols.getEras();
            String[] months = symbols.getMonths();
            String[] shortMonths = symbols.getShortMonths();
            String[] weekdays = symbols.getWeekdays();
            String[] shortWeekdays = symbols.getShortWeekdays();
            String[] AmPmStrings = symbols.getAmPmStrings();

            int length = mPattern.length();
            int[] indexRef = new int[1];

            for (int i = 0; i < length; i++) {
                indexRef[0] = i;
                String token = parseToken(mPattern, indexRef);
                i = indexRef[0];

                int tokenLen = token.length();
                if (tokenLen == 0) {
                    break;
                }

                Rule rule;
                char c = token.charAt(0);

                switch (c) {
                    case 'G': // era designator (text)
                        rule = new TextField(Calendar.ERA, ERAs);
                        break;
                    case 'y': // year (number)
                        if (tokenLen >= 4) {
                            rule = selectNumberRule(Calendar.YEAR, tokenLen);
                        } else {
                            rule = TwoDigitYearField.INSTANCE;
                        }
                        break;
                    case 'M': // month in year (text and number)
                        if (tokenLen >= 4) {
                            rule = new TextField(Calendar.MONTH, months);
                        } else if (tokenLen == 3) {
                            rule = new TextField(Calendar.MONTH, shortMonths);
                        } else if (tokenLen == 2) {
                            rule = TwoDigitMonthField.INSTANCE;
                        } else {
                            rule = UnpaddedMonthField.INSTANCE;
                        }
                        break;
                    case 'd': // day in month (number)
                        rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen);
                        break;
                    case 'h': // hour in am/pm (number, 1..12)
                        rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen));
                        break;
                    case 'H': // hour in day (number, 0..23)
                        rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen);
                        break;
                    case 'm': // minute in hour (number)
                        rule = selectNumberRule(Calendar.MINUTE, tokenLen);
                        break;
                    case 's': // second in minute (number)
                        rule = selectNumberRule(Calendar.SECOND, tokenLen);
                        break;
                    case 'S': // millisecond (number)
                        rule = selectNumberRule(Calendar.MILLISECOND, tokenLen);
                        break;
                    case 'E': // day in week (text)
                        rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays);
                        break;
                    case 'D': // day in year (number)
                        rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen);
                        break;
                    case 'F': // day of week in month (number)
                        rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen);
                        break;
                    case 'w': // week in year (number)
                        rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen);
                        break;
                    case 'W': // week in month (number)
                        rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen);
                        break;
                    case 'a': // am/pm marker (text)
                        rule = new TextField(Calendar.AM_PM, AmPmStrings);
                        break;
                    case 'k': // hour in day (1..24)
                        rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen));
                        break;
                    case 'K': // hour in am/pm (0..11)
                        rule = selectNumberRule(Calendar.HOUR, tokenLen);
                        break;
                    case 'z': // time zone (text)
                        if (tokenLen >= 4) {
                            rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.LONG);
                        } else {
                            rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.SHORT);
                        }
                        break;
                    case 'Z': // time zone (value)
                        if (tokenLen == 1) {
                            rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
                        } else {
                            rule = TimeZoneNumberRule.INSTANCE_COLON;
                        }
                        break;
                    case '\'': // literal text
                        String sub = token.substring(1);
                        if (sub.length() == 1) {
                            rule = new CharacterLiteral(sub.charAt(0));
                        } else {
                            rule = new StringLiteral(sub);
                        }
                        break;
                    default:
                        throw new IllegalArgumentException("Illegal pattern component: " + token);
                }

                rules.add(rule);
            }

            return rules;
        }

        /**
         * 功能描述:
         * 〈解析格式pattern〉
         *
         * @params : [pattern, indexRef]
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:47
         */
        private String parseToken(String pattern, int[] indexRef) {
            StringBuffer buf = new StringBuffer();

            int i = indexRef[0];
            int length = pattern.length();

            char c = pattern.charAt(i);
            if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
                // Scan a run of the same character, which indicates a time
                // pattern.
                buf.append(c);

                while (i + 1 < length) {
                    char peek = pattern.charAt(i + 1);
                    if (peek == c) {
                        buf.append(c);
                        i++;
                    } else {
                        break;
                    }
                }
            } else {
                // This will identify token as text.
                buf.append('\'');

                boolean inLiteral = false;

                for (; i < length; i++) {
                    c = pattern.charAt(i);

                    if (c == '\'') {
                        if (i + 1 < length && pattern.charAt(i + 1) == '\'') {
                            // '' is treated as escaped '
                            i++;
                            buf.append(c);
                        } else {
                            inLiteral = !inLiteral;
                        }
                    } else if (!inLiteral &&
                            (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
                        i--;
                        break;
                    } else {
                        buf.append(c);
                    }
                }
            }

            indexRef[0] = i;
            return buf.toString();
        }

        /**
         * 功能描述:
         * 〈获取所需要的数字规则〉
         *
         * @params : [field, padding]
         * @return : com.simple.util.time.DateUtil.FastDateFormat.NumberRule
         * @author : cwl
         * @date : 2019/6/4 17:48
         */
        private NumberRule selectNumberRule(int field, int padding) {
            switch (padding) {
                case 1:
                    return new UnpaddedNumberField(field);
                case 2:
                    return new TwoDigitNumberField(field);
                default:
                    return new PaddedNumberField(field, padding);
            }
        }

        /**
         * 功能描述:
         * 〈格式化Date或者Calender日期类〉
         *
         * @params : [obj, toAppendTo, pos]
         * @return : java.lang.StringBuffer
         * @author : cwl
         * @date : 2019/6/4 17:50
         */
        @Override
        public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
            if (obj instanceof Date) {
                return format((Date) obj, toAppendTo);
            } else if (obj instanceof Calendar) {
                return format((Calendar) obj, toAppendTo);
            } else if (obj instanceof Long) {
                return format(((Long) obj).longValue(), toAppendTo);
            } else {
                throw new IllegalArgumentException("Unknown class: " +
                        (obj == null ? "<null>" : obj.getClass().getName()));
            }
        }

        /**
         * 功能描述:
         * 〈格式化毫秒数〉
         *
         * @params : [millis]
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:50
         */
        public String format(long millis) {
            return format(new Date(millis));
        }

        /**
         * 功能描述:
         * 〈格式化date日期类〉
         *
         * @params : [date]
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:51
         */
        public String format(Date date) {
            Calendar c = new GregorianCalendar(mTimeZone);
            c.setTime(date);
            return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString();
        }

        /**
         * 功能描述:
         * 〈格式化Clalendar日期〉
         *
         * @params : [calendar]
         * @return : java.lang.String
         * @author : cwl
         * @date : 2019/6/4 17:52
         */
        public String format(Calendar calendar) {
            return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString();
        }

        /**
         * 功能描述:
         * 〈格式化毫秒数,结果缓存到buf当中〉
         *
         * @params : [millis, buf]
         * @return : java.lang.StringBuffer
         * @author : cwl
         * @date : 2019/6/4 17:52
         */
        public StringBuffer format(long millis, StringBuffer buf) {
            return format(new Date(millis), buf);
        }

        /**
         * 功能描述:
         * 〈格式化Date日期类型,并且将结果缓存到buf当中〉
         *
         * @params : [date, buf]
         * @return : java.lang.StringBuffer
         * @author : cwl
         * @date : 2019/6/4 17:53
         */
        public StringBuffer format(Date date, StringBuffer buf) {
            Calendar c = new GregorianCalendar(mTimeZone);
            c.setTime(date);
            return applyRules(c, buf);
        }

        /**
         * 功能描述:
         * 〈格式化Calendar日期类型,并且将结果缓存到buf当中〉
         *
         * @params : [calendar, buf]
         * @return : java.lang.StringBuffer
         * @author : cwl
         * @date : 2019/6/4 17:54
         */
        public StringBuffer format(Calendar calendar, StringBuffer buf) {
            if (mTimeZoneForced) {
                calendar = (Calendar) calendar.clone();
                calendar.setTimeZone(mTimeZone);
            }
            return applyRules(calendar, buf);
        }

        /**
         * 功能描述:
         * 〈通过将规则应用于指定的日历来执行格式化〉
         *
         * @params : [calendar, buf]
         * @return : java.lang.StringBuffer
         * @author : cwl
         * @date : 2019/6/4 17:55
         */
        private StringBuffer applyRules(Calendar calendar, StringBuffer buf) {
            Rule[] rules = mRules;
            int len = mRules.length;
            for (int i = 0; i < len; i++) {
                rules[i].appendTo(buf, calendar);
            }
            return buf;
        }

        public String getmPattern() {
            return mPattern;
        }

        public TimeZone getmTimeZone() {
            return mTimeZone;
        }

        public boolean ismTimeZoneForced() {
            return mTimeZoneForced;
        }

        public Locale getmLocale() {
            return mLocale;
        }

        public boolean ismLocaleForced() {
            return mLocaleForced;
        }

        public int getmMaxLengthEstimate() {
            return mMaxLengthEstimate;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof FastDateFormat == false) {
                return false;
            }
            FastDateFormat other = (FastDateFormat) obj;
            if (
                    (mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
                            (mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
                            (mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
                            (mTimeZoneForced == other.mTimeZoneForced) &&
                            (mLocaleForced == other.mLocaleForced)
            ) {
                return true;
            }
            return false;
        }

        @Override
        public int hashCode() {
            int total = 0;
            total += mPattern.hashCode();
            total += mTimeZone.hashCode();
            total += (mTimeZoneForced ? 1 : 0);
            total += mLocale.hashCode();
            total += (mLocaleForced ? 1 : 0);
            return total;
        }

        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            init();
        }

        @Override
        public String toString() {
            return "FastDateFormat[" + mPattern + "]";
        }
        //用于定义一个规则的接口
        private interface Rule {

            /**
             * 功能描述:
             * 〈返回预计的长度〉
             *
             * @params : []
             * @return : int
             * @author : cwl
             * @date : 2019/6/4 16:47
             */
            int estimateLength();

            /**
             * 功能描述:
             * 〈根据规则实现将指定日历的值添加到StringBuffer缓存当中〉
             *
             * @params : [buffer, calendar]
             * @return : void
             * @author : cwl
             * @date : 2019/6/4 16:48
             */
            void appendTo(StringBuffer buffer, Calendar calendar);
        }

        //定义一个数字的规则
        private interface NumberRule extends Rule {

            /**
             * 功能描述:
             * 〈将指定值添加到buffer当中〉
             *
             * @params : [buffer, value]
             * @return : void
             * @author : cwl
             * @date : 2019/6/4 16:50
             */
            void appendTo(StringBuffer buffer, int value);
        }

        //输出一个常量的字符
        private static class CharacterLiteral implements Rule {
            private final char mValue;

            CharacterLiteral(char value) {
                mValue = value;
            }

            public int estimateLength() {
                return 1;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                buffer.append(mValue);
            }
        }
        @Override
        public Object parseObject(String source, ParsePosition pos) {
            pos.setIndex(0);
            pos.setErrorIndex(0);
            return null;
        }

        //用于输出一个常量字符
        private static class StringLiteral implements Rule {
            private final String mValue;

            StringLiteral(String value) {
                mValue = value;
            }

            public int estimateLength() {
                return mValue.length();
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                buffer.append(mValue);
            }
        }

        //输出一组值当中的一个
        private static class TextField implements Rule {
            private final int mField;
            private final String[] mValues;

            TextField(int field, String[] values) {
                mField = field;
                mValues = values;
            }
            public int estimateLength() {
                int max = 0;
                for (int i=mValues.length; --i >= 0; ) {
                    int len = mValues[i].length();
                    if (len > max) {
                        max = len;
                    }
                }
                return max;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                buffer.append(mValues[calendar.get(mField)]);
            }
        }

        //输出年份
        private static class UnpaddedNumberField implements NumberRule {
            static final UnpaddedNumberField INSTANCE_YEAR = new UnpaddedNumberField(Calendar.YEAR);

            private final int mField;

            UnpaddedNumberField(int field) {
                mField = field;
            }

            public int estimateLength() {
                return 4;
            }
            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(mField));
            }
            public final void appendTo(StringBuffer buffer, int value) {
                if (value < 10) {
                    buffer.append((char)(value + '0'));
                } else if (value < 100) {
                    buffer.append((char)(value / 10 + '0'));
                    buffer.append((char)(value % 10 + '0'));
                } else {
                    buffer.append(Integer.toString(value));
                }
            }
        }

        //输出月份
        private static class UnpaddedMonthField implements NumberRule {
            static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();
            UnpaddedMonthField() {
                super();
            }
            public int estimateLength() {
                return 2;
            }
            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
            }
            public final void appendTo(StringBuffer buffer, int value) {
                if (value < 10) {
                    buffer.append((char)(value + '0'));
                } else {
                    buffer.append((char)(value / 10 + '0'));
                    buffer.append((char)(value % 10 + '0'));
                }
            }
        }

        //用于填充两位数的内部类
        private static class PaddedNumberField implements NumberRule {
            private final int mField;
            private final int mSize;

            PaddedNumberField(int field, int size) {
                if (size < 3) {
                    // Should use UnpaddedNumberField or TwoDigitNumberField.
                    throw new IllegalArgumentException();
                }
                mField = field;
                mSize = size;
            }
            public int estimateLength() {
                return 4;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(mField));
            }

            public final void appendTo(StringBuffer buffer, int value) {
                if (value < 100) {
                    for (int i = mSize; --i >= 2; ) {
                        buffer.append('0');
                    }
                    buffer.append((char)(value / 10 + '0'));
                    buffer.append((char)(value % 10 + '0'));
                } else {
                    int digits;
                    if (value < 1000) {
                        digits = 3;
                    } else {
                        if(value <= -1){
                            throw new IllegalArgumentException("Negative values should not be possible" + value);
                        }
                        digits = Integer.toString(value).length();
                    }
                    for (int i = mSize; --i >= digits; ) {
                        buffer.append('0');
                    }
                    buffer.append(Integer.toString(value));
                }
            }
        }

        //用来输出两位数的内部类
        private static class TwoDigitNumberField implements NumberRule {
            private final int mField;

            TwoDigitNumberField(int field) {
                mField = field;
            }

            public int estimateLength() {
                return 2;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(mField));
            }

            public final void appendTo(StringBuffer buffer, int value) {
                if (value < 100) {
                    buffer.append((char)(value / 10 + '0'));
                    buffer.append((char)(value % 10 + '0'));
                } else {
                    buffer.append(Integer.toString(value));
                }
            }
        }

        //用来输出两位数字的年份的内部类
        private static class TwoDigitYearField implements NumberRule {
            static final TwoDigitYearField INSTANCE = new TwoDigitYearField();

            TwoDigitYearField() {
                super();
            }

            public int estimateLength() {
                return 2;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
            }

            public final void appendTo(StringBuffer buffer, int value) {
                buffer.append((char)(value / 10 + '0'));
                buffer.append((char)(value % 10 + '0'));
            }
        }

        //用来输出两位数字的月份的内部类
        private static class TwoDigitMonthField implements NumberRule {
            static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();

            TwoDigitMonthField() {
                super();
            }

            public int estimateLength() {
                return 2;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
            }

            public final void appendTo(StringBuffer buffer, int value) {
                buffer.append((char)(value / 10 + '0'));
                buffer.append((char)(value % 10 + '0'));
            }
        }
        //用来输出12小时字段的内部类
        private static class TwelveHourField implements NumberRule {
            private final NumberRule mRule;
            TwelveHourField(NumberRule rule) {
                mRule = rule;
            }

            public int estimateLength() {
                return mRule.estimateLength();
            }
            public void appendTo(StringBuffer buffer, Calendar calendar) {
                int value = calendar.get(Calendar.HOUR);
                if (value == 0) {
                    value = calendar.getLeastMaximum(Calendar.HOUR) + 1;
                }
                mRule.appendTo(buffer, value);
            }
            public void appendTo(StringBuffer buffer, int value) {
                mRule.appendTo(buffer, value);
            }
        }

        //用来输出24小时字段的内部类
        private static class TwentyFourHourField implements NumberRule {
            private final NumberRule mRule;

            TwentyFourHourField(NumberRule rule) {
                mRule = rule;
            }
            public int estimateLength() {
                return mRule.estimateLength();
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                int value = calendar.get(Calendar.HOUR_OF_DAY);
                if (value == 0) {
                    value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1;
                }
                mRule.appendTo(buffer, value);
            }
            public void appendTo(StringBuffer buffer, int value) {
                mRule.appendTo(buffer, value);
            }
        }

        //用来输出时区名称的内部类
        private static class TimeZoneNameRule implements Rule {
            private final TimeZone mTimeZone;
            private final boolean mTimeZoneForced;
            private final Locale mLocale;
            private final int mStyle;
            private final String mStandard;
            private final String mDaylight;

            TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style) {
                mTimeZone = timeZone;
                mTimeZoneForced = timeZoneForced;
                mLocale = locale;
                mStyle = style;

                if (timeZoneForced) {
                    mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
                    mDaylight = getTimeZoneDisplay(timeZone, true, style, locale);
                } else {
                    mStandard = null;
                    mDaylight = null;
                }
            }

            public int estimateLength() {
                if (mTimeZoneForced) {
                    return Math.max(mStandard.length(), mDaylight.length());
                } else if (mStyle == TimeZone.SHORT) {
                    return 4;
                } else {
                    return 40;
                }
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                if (mTimeZoneForced) {
                    if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
                        buffer.append(mDaylight);
                    } else {
                        buffer.append(mStandard);
                    }
                } else {
                    TimeZone timeZone = calendar.getTimeZone();
                    if (timeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
                        buffer.append(getTimeZoneDisplay(timeZone, true, mStyle, mLocale));
                    } else {
                        buffer.append(getTimeZoneDisplay(timeZone, false, mStyle, mLocale));
                    }
                }
            }
        }

        //将时区作为数字输出的内部类
        private static class TimeZoneNumberRule implements Rule {
            static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
            static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);

            final boolean mColon;

            TimeZoneNumberRule(boolean colon) {
                mColon = colon;
            }

            public int estimateLength() {
                return 5;
            }

            public void appendTo(StringBuffer buffer, Calendar calendar) {
                int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);

                if (offset < 0) {
                    buffer.append('-');
                    offset = -offset;
                } else {
                    buffer.append('+');
                }

                int hours = offset / (60 * 60 * 1000);
                buffer.append((char)(hours / 10 + '0'));
                buffer.append((char)(hours % 10 + '0'));

                if (mColon) {
                    buffer.append(':');
                }

                int minutes = offset / (60 * 1000) - 60 * hours;
                buffer.append((char)(minutes / 10 + '0'));
                buffer.append((char)(minutes % 10 + '0'));
            }
        }

        //时区名称作为Key值的内部类
        private static class TimeZoneDisplayKey {
            private final TimeZone mTimeZone;
            private final int mStyle;
            private final Locale mLocale;

            TimeZoneDisplayKey(TimeZone timeZone,
                               boolean daylight, int style, Locale locale) {
                mTimeZone = timeZone;
                if (daylight) {
                    style |= 0x80000000;
                }
                mStyle = style;
                mLocale = locale;
            }

            public int hashCode() {
                return mStyle * 31 + mLocale.hashCode();
            }

            public boolean equals(Object obj) {
                if (this == obj) {
                    return true;
                }
                if (obj instanceof TimeZoneDisplayKey) {
                    TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj;
                    return
                            mTimeZone.equals(other.mTimeZone) &&
                                    mStyle == other.mStyle &&
                                    mLocale.equals(other.mLocale);
                }
                return false;
            }
        }

        // 用于创建复合对象的Helper类
        private static class Pair {
            private final Object mObj1;
            private final Object mObj2;

            public Pair(Object obj1, Object obj2) {
                mObj1 = obj1;
                mObj2 = obj2;
            }

            public boolean equals(Object obj) {
                if (this == obj) {
                    return true;
                }

                if (!(obj instanceof Pair)) {
                    return false;
                }

                Pair key = (Pair)obj;

                return
                        (mObj1 == null ?
                                key.mObj1 == null : mObj1.equals(key.mObj1)) &&
                                (mObj2 == null ?
                                        key.mObj2 == null : mObj2.equals(key.mObj2));
            }

            public int hashCode() {
                return (mObj1 == null ? 0 : mObj1.hashCode()) + (mObj2 == null ? 0 : mObj2.hashCode());
            }
            public String toString() {
                return "[" + mObj1 + ':' + mObj2 + ']';
            }
        }
    }
}
